import os
import subprocess
import re
from tkinter import Tk, Frame, PhotoImage, filedialog, messagebox, Canvas, Scrollbar
from ttkbootstrap import Style, Button, Entry, Label as TtkLabel

def get_ffmpeg_path():
    script_dir = os.path.dirname(os.path.abspath(__file__))
    ffmpeg_path = os.path.join(script_dir, "bin", "ffmpeg.exe")
    return ffmpeg_path
def get_video_info(video_path):
    ffmpeg_path = get_ffmpeg_path()
    result = subprocess.run([ffmpeg_path, "-i", video_path], capture_output=True, text=True, encoding='utf-8')
    output = result.stderr
    frame_rate_match = re.search(r"(\d+) fps", output)
    resolution_match = re.search(r"(\d+)x(\d+)", output)
    duration_match = re.search(r"Duration: (\d{2}:\d{2}:\d{2})", output)
    frame_rate = frame_rate_match.group(1) if frame_rate_match else "未知"
    resolution = f"{resolution_match.group(1)}x{resolution_match.group(2)}" if resolution_match else "未知"
    duration = duration_match.group(1) if duration_match else "未知"
    if resolution == "0x1":
        resolution_match = re.search(r"Stream #.*: Video:.* (\d+)x(\d+)", output)
        resolution = f"{resolution_match.group(1)}x{resolution_match.group(2)}" if resolution_match else "未知"
    return frame_rate, resolution, duration
def convert_and_merge_videos(video_paths, output_names):
    ffmpeg_path = get_ffmpeg_path()
    script_dir = os.path.dirname(os.path.abspath(__file__))
    video_dir = os.path.join(script_dir, "video")
    output_dir = os.path.join(video_dir, "output")
    if not os.path.exists(video_dir):
        os.makedirs(video_dir)
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    ts1_path = os.path.join(video_dir, "pt.ts")
    for index, video_path in enumerate(video_paths):
        base_name = os.path.splitext(os.path.basename(video_path))[0]
        ts2_path = os.path.join(video_dir, f"{base_name}.ts")
        output_name = output_names[index] if index < len(output_names) else f"{index + 1:02d}_{base_name}"
        output_path = os.path.join(output_dir, f"{output_name}.mp4")

        subprocess.run([ffmpeg_path, "-i", video_path, "-c", "copy", ts2_path])
        subprocess.run([ffmpeg_path, "-i", f"concat:{ts1_path}|{ts2_path}", "-c", "copy", "-bsf:a", "aac_adtstoasc", "-movflags", "+faststart", output_path])

        os.remove(ts2_path)
    messagebox.showinfo("成功", f"视频已输出到{output_dir}")
    os.startfile(output_dir)
def select_videos(video_frame, output_names_frame):
    global video_paths, output_names_entries
    video_paths = filedialog.askopenfilenames(title="Select Videos", filetypes=[("Video files", "*.mp4 *.avi *.mkv *.ts")])
    for widget in video_frame.winfo_children():
        widget.destroy()

    for widget in output_names_frame.winfo_children():
        widget.destroy()
    script_dir = os.path.dirname(os.path.abspath(__file__))
    icon_path = os.path.join(script_dir, "bin", "icon", "video.png")
    icon = PhotoImage(file=icon_path)
    row, col = 0, 0
    output_names_entries = []
    for index, video_path in enumerate(video_paths):
        base_name = os.path.splitext(os.path.basename(video_path))[0]
        display_name = base_name
        if len(display_name) > 15:
            display_name = display_name[:12] + "..."
        label = TtkLabel(video_frame, image=icon, text=display_name, compound='top', style='TLabel')
        label.image = icon
        label.grid(row=row, column=col, padx=10, pady=10)
        col += 1
        if col == 5:
            col = 0
            row += 1
        TtkLabel(output_names_frame, text=f"输出视频标题 {index + 1}:", style='TLabel').grid(row=index, column=0, padx=10, pady=10)
        entry = Entry(output_names_frame, width=50, style='TEntry')
        entry.grid(row=index, column=1, padx=10, pady=10)
        entry.insert(0, f"{index + 1}_{base_name}")
        output_names_entries.append(entry)
    update_scroll()  # 更新滚动条显示状态
    return output_names_entries
def merge_videos(video_paths, output_names_entries):
    video_paths = video_paths.split('|')
    output_names = [entry.get() for entry in output_names_entries]
    convert_and_merge_videos(video_paths, output_names)

root = Tk()
style = Style(theme='journal')
root.title("课程片头合并")
root.resizable(False, False)
script_dir = os.path.dirname(os.path.abspath(__file__))
root.iconbitmap(os.path.join(script_dir, "bin", "icon", "icon.ico"))
TtkLabel(root, text="课程视频:", style='TLabel').grid(row=0, column=0, padx=10, pady=10)
Button(root, text="选择视频", command=lambda: select_videos(video_frame, output_names_frame), style='TButton').grid(row=0, column=1, columnspan=2, padx=10, pady=10, sticky="ew")
canvas = Canvas(root)
scrollbar = Scrollbar(root, orient="vertical", command=canvas.yview)
scrollable_frame = Frame(canvas)

scrollable_frame.bind(
    "<Configure>",
    lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
video_frame = Frame(root)
video_frame.grid(row=1, column=0, columnspan=3, padx=10, pady=10, sticky="nsew")
output_names_canvas = Canvas(root, width=620)
output_names_scrollbar = Scrollbar(root, orient="vertical", command=output_names_canvas.yview)
output_names_frame = Frame(output_names_canvas)
output_names_frame.bind(
    "<Configure>",
    lambda e: output_names_canvas.configure(scrollregion=output_names_canvas.bbox("all"))
)
output_names_canvas.create_window((0, 0), window=output_names_frame, anchor="nw")
output_names_canvas.configure(yscrollcommand=output_names_scrollbar.set)
# 绑定鼠标滚轮事件
def on_mousewheel(event):
    output_names_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
output_names_canvas.bind("<MouseWheel>", on_mousewheel)
Button(root, text="开始处理", command=lambda: merge_videos('|'.join(video_paths), output_names_entries), style='TButton').grid(row=3, column=0, columnspan=3, padx=10, pady=10, sticky="ew")
TtkLabel(root, text="Powered by Suyi @2024 www.cwh-cg.com", style='TLabel').grid(row=4, column=1, columnspan=2, padx=10, pady=10, sticky="ew")
# 如果条目超过5个，显示滚动条
# 移除之前的update_scroll函数中关于忘记滚动条的代码，并添加新的逻辑来控制滚动条的显示
def update_scroll():
    global video_paths
    if len(video_paths) <= 5:
        # 当视频数量少于等于5时，可以将滚动条的宽度设为0或使用不可见的样式，当视频数量少于等于5时禁止滚动条功能
        canvas.config(yscrollcommand=None)
        output_names_scrollbar.config(width=0)
    else:
        # 当视频数量超过8时，恢复滚动条的宽度和功能
        output_names_scrollbar.config(width=15)  # 假设原本宽度为15，根据实际需要调整

    # 确保Canvas和滚动条的位置布局不受影响，始终存在
    output_names_canvas.grid(row=2, column=0, columnspan=2, padx=10, pady=10, sticky="nsew")
    output_names_scrollbar.grid(row=2, column=2, sticky="ns")

# 在初始化或适当位置调用update_scroll来设置初始状态
root.after(100, update_scroll)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1)
root.grid_columnconfigure(0, weight=1)
# 初始化 video_paths 为空列表
video_paths = []
root.after(100, update_scroll)
root.mainloop()
